package arp.analiseprestadores.dados;

import arp.analiseprestadores.model.Prestador;
import arp.analiseprestadores.util.ConstantesARP;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 *
 * @author maddogxx
 */
public class RepositorioPrestador {
    
    private static String QUERY_INSERT_ORIGEM = "INSERT INTO " + ConstantesARP.NOME_TABELA_ORIGEM + " (documento, nome) VALUES (?, ?)";
    private static String QUERY_INSERT_DESTINO = "INSERT INTO " + ConstantesARP.NOME_TABELA_DESTINO + " (documento, nome) VALUES (?, ?)";
    private static String QUERY_FIND_ALL = "SELECT * FROM #";
    private static String QUERY_CONSULTAR_DIFERENCA_PRESTADORES = "SELECT * FROM #1 tab1 WHERE tab1.documento NOT IN (SELECT tab2.documento FROM #2 tab2)";
    private static String QUERY_CONSULTAR_INTERSECCAO_PRESTADORES = "SELECT tab1.documento, tab1.nome AS nomeOrigem, tab2.nome AS nomeDestino FROM " + ConstantesARP.NOME_TABELA_ORIGEM + " tab1 JOIN " + ConstantesARP.NOME_TABELA_DESTINO + " tab2 ON (tab2.documento = tab1.documento)";
    
    private static RepositorioPrestador instancia = null;
    
    private JdbcTemplate jdbcTemplate;
    
    private RepositorioPrestador() {
        ApplicationContext context = new ClassPathXmlApplicationContext(ConstantesARP.ARQUIVO_CONTEXTO);

        jdbcTemplate = new JdbcTemplate((DataSource) context.getBean("dataSource"));
    }
    
    public static RepositorioPrestador getInstancia() {
        if (instancia == null) {
            instancia = new RepositorioPrestador();
        }
        
        return instancia;
    }
    
    public void inserirBatch(final List<Prestador> prestadores, boolean isOrigem) {
        if (isOrigem) {
            jdbcTemplate.batchUpdate(QUERY_INSERT_ORIGEM, new BatchPreparedStatementSetter() {

                    @Override
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                            Prestador prestador = prestadores.get(i);
                            ps.setString(1, prestador.getDocumento());
                            ps.setString(2, prestador.getNome());
                    }

                    @Override
                    public int getBatchSize() {
                            return prestadores.size();
                    }
            });
        } else {
            jdbcTemplate.batchUpdate(QUERY_INSERT_DESTINO, new BatchPreparedStatementSetter() {

                    @Override
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                            Prestador prestador = prestadores.get(i);
                            ps.setString(1, prestador.getDocumento());
                            ps.setString(2, prestador.getNome());
                    }

                    @Override
                    public int getBatchSize() {
                            return prestadores.size();
                    }
            });            
        }
    }
    
    public List<Prestador> findAll(boolean isOrigem) {
        String sql = QUERY_FIND_ALL.replaceAll("#", ConstantesARP.NOME_TABELA_ORIGEM);
        
        if (!isOrigem) {
            sql = QUERY_FIND_ALL.replaceAll("#", ConstantesARP.NOME_TABELA_DESTINO); 
        }

        List<Prestador> prestadores = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Prestador.class));

        return prestadores;
    }
    
    public List<Prestador> consultarDiferencaPrestadores(boolean isOrigem) {
        String sql = QUERY_CONSULTAR_DIFERENCA_PRESTADORES.replaceAll("#1", ConstantesARP.NOME_TABELA_ORIGEM).replaceAll("#2", ConstantesARP.NOME_TABELA_DESTINO);
        
        if (!isOrigem) {
            sql = QUERY_CONSULTAR_DIFERENCA_PRESTADORES.replaceAll("#1", ConstantesARP.NOME_TABELA_DESTINO).replaceAll("#2", ConstantesARP.NOME_TABELA_ORIGEM);
        }
        
        List<Prestador> prestadores = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Prestador.class));

        return prestadores;
    }
    
    public List<Map<String, String>> consultarInterseccaoPrestadores() {
        String sql = QUERY_CONSULTAR_INTERSECCAO_PRESTADORES;
        
        List<Map<String, String>> resultado = new ArrayList<Map<String, String>>();
        
        List<Map<String, Object>> linhas = jdbcTemplate.queryForList(sql);
        
        for (Map<String, Object> linha : linhas) {
            Map<String, String> mapa = new HashMap<String, String>();
            
            mapa.put(ConstantesARP.NOME_COLUNA_DOCUMENTO, (String) linha.get(ConstantesARP.NOME_COLUNA_DOCUMENTO));
            mapa.put(ConstantesARP.NOME_COLUNA_ORIGEM, (String) linha.get(ConstantesARP.NOME_COLUNA_ORIGEM));
            mapa.put(ConstantesARP.NOME_COLUNA_DESTINO, (String) linha.get(ConstantesARP.NOME_COLUNA_DESTINO));
            
            resultado.add(mapa);
        }
        
        return resultado;
    }
    
    public void resetarBase() {
        jdbcTemplate.update("drop table if exists " + ConstantesARP.NOME_TABELA_ORIGEM);
        jdbcTemplate.update("drop table if exists " + ConstantesARP.NOME_TABELA_DESTINO);
        jdbcTemplate.update("create table " + ConstantesARP.NOME_TABELA_ORIGEM + "(  id identity,  documento character varying(14) not null,  nome character varying(255),  constraint origem_pk primary key (id))");
        jdbcTemplate.update("create table " + ConstantesARP.NOME_TABELA_DESTINO + "(  id identity,  documento character varying(14) not null,  nome character varying(255),  constraint destino_pk primary key (id))");        
    }
    
    public void conciliar() {
        
    }
}